package com.example;

import org.junit.jupiter.api.Test;

import java.util.concurrent.*;

public class Demo01Test {
    @Test
    public void test01() throws Exception{
        System.out.println("======begin========");
        // 可以使用如下无参构造函数简单的创建 CompletableFuture：
        CompletableFuture<String> completableFuture = new CompletableFuture<>();
        String result ;
        try {
            // 想获取 CompletableFuture 的结果可以使用 CompletableFuture.get(long timeout, TimeUnit unit) 方法
            result = completableFuture.get(2, TimeUnit.SECONDS);
        } catch (Exception e) {
            // 使用 CompletableFuture.complete() 手工的完成一个 Future
            completableFuture.complete("Future's Result");
            // get() 方法会一直阻塞直到 Future 完成
            result = completableFuture.get();
        }
        System.out.println("result = " + result);
        System.out.println("======end========");
    }

    /**
     * 使用 runAsync() 运行异步计算
     * 如果你想异步的运行一个后台任务并且不想该任务返回任务东西，
     * 这时候可以使用 CompletableFuture.runAsync()方法，
     * 它持有一个 Runnable 对象，并返回 CompletableFuture<Void>。
     */
    @Test
    public void test02() throws Exception{
        CompletableFuture<Void> completableFuture = CompletableFuture.runAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("I'll run in a separate thread than the main thread.");
        });
        completableFuture.get();
    }

    /**
     * 使用 supplyAsync() 运行一个异步任务并且返回结果
     * 如果你想异步的运行一个后台任务并且返回一些结果，
     * 这时候可以使用 CompletableFuture.supplyAsync()方法，
     * 它持有 Supplier<T> 并且返回 CompletableFuture<T>，T 是通过调用 传入的 supplier 的返回类型。
     *
     * 一个关于Executor 和Thread Pool笔记
     * 你可能想知道，我们知道runAsync()和supplyAsync()方法在单独的线程中执行他们的任务。但是我们不会永远只创建一个线程。
     * CompletableFuture可以从全局的 ForkJoinPool.commonPool()获得一个线程中执行这些任务。
     * 但是你也可以创建一个线程池并传给runAsync()和supplyAsync()方法来让他们从线程池中获取一个线程执行它们的任务。
     * CompletableFuture API 的所有方法都有两个变体-一个接受Executor作为参数，另一个不这样：
     */
    @Test
    public void test03() throws Exception{
        ThreadPoolExecutor executor = new ThreadPoolExecutor(50,200,5,TimeUnit.MINUTES,
                new LinkedBlockingQueue<>(1000),new ThreadPoolExecutor.CallerRunsPolicy());

        CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "Result of the asynchronous computation";
        },executor);
        String result = completableFuture.get();
        System.out.println("result = " + result);
    }

}
